package com.sharkpro.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.sharkpro.constants.RedisConstant;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.crypto.SecretKey;
import java.util.concurrent.TimeUnit;


@Component
@Slf4j
public class RedisUtil {
    @Autowired
    private RedissonClient client;

    /**
     * 初始化布隆过滤器
     *
     * @param bloomName          布隆过滤器名称
     * @param expectedInsertions 预期大小
     * @param falseProbability   误差概率
     * @param timeout            过期时间
     * @param timeUnit           时间单位
     * @param key                需要插入布隆过滤器的key
     */
    private void initBloomFilter(String bloomName, long expectedInsertions, double falseProbability, long timeout, TimeUnit timeUnit,
                                 String key) {
        boolean flag;
        try {
            RBloomFilter bloomFilter = client.getBloomFilter(bloomName);
            try {
                flag = bloomFilter.getSize() != 0 && bloomFilter.getHashIterations() != 0;
            } catch (Exception e) {
                flag = false;
            }
            if (flag) {
                log.info(StrUtil.format("布隆过滤器：{}已存在", bloomName));
                bloomFilter.add(key);
                return;
            }
            bloomFilter.tryInit(expectedInsertions, falseProbability);
            if (timeout > 0) {
                bloomFilter.expire(timeout, timeUnit);
            }
            log.info(StrUtil.format("布隆过滤器：{}初始化配置成功", bloomName));
            bloomFilter.add(key);
        } catch (Exception e) {
            log.info(StrUtil.format("布隆过滤器：{}初始化配置失败", bloomName), e);
        }
    }

    /**
     * 存储Map
     * 存储之前会先初始化布隆过滤器
     *
     * @param rkey       缓存池名称
     * @param key        存储key
     * @param value      存储value
     * @param timeToLive 超时时间 小于0永久保存 单位：毫秒
     * @param timeUnit   时间单位
     */
    public void setMapCache(String rkey, String key, Object value, long timeToLive, TimeUnit timeUnit) {
        try {
            String bloomName = rkey + "Bloom";
            initBloomFilter(bloomName, 9000000, 0.01, -1, TimeUnit.SECONDS, key);
            RMapCache<String, Object> mapCache = client.getMapCache(rkey);
            if (timeToLive < 0) {
                timeToLive = 600;
                timeUnit = TimeUnit.SECONDS;
            }
                mapCache.put(key, Base64.encode(value.toString()), timeToLive, timeUnit);
                log.info("redis设置缓存成功，rkey:"+rkey+",key:"+key);
        } catch (Exception e) {
            log.info("redis设置缓存异常",e);
        }
    }

    /**
     * 获取缓存
     *
     * @param rkey 缓存池名称
     * @param key  存储key
     * @return Object 存储value
     */
    public Object getMapCache(String rkey, String key) {
        try {
            RMapCache<String, Object> mapCache = client.getMapCache(rkey);
            Object o =  mapCache.get(key);
            if (ObjectUtils.isEmpty(o)) {
                return null;
            }
//            String REDIS_SALT = "wjx&0010wjx&0010";
//            byte[] REDIS_SALT_BYTE = REDIS_SALT.getBytes();
            String value = Base64.decodeStr(o.toString());
            log.info("redis获取缓存成功，key:"+key);

            return value;
        } catch (Exception e) {
            log.info("获取缓存异常",e);
            return null;
        }
    }

    /**
     * 校验缓存充是否存在key
     *
     * @param rkey 缓存池名称
     * @param key  存储key
     * @return boolean
     */
    public boolean containsMapKey(String rkey, String key) {
        try {
            boolean flag = false;
            String bloomName = rkey + "Bloom";
            try {
                RBloomFilter bloomFilter = client.getBloomFilter(bloomName);
                flag = bloomFilter.contains(key);
            } catch (Exception e) {
                flag = false;
            }
            if (!flag) {
                return false;
            }
            RMapCache<Object, Object> mapCache = client.getMapCache(rkey);
            if (mapCache.isExists()) {
                return mapCache.containsKey(key);
            } else {
                return false;
            }
        } catch (Exception e) {
            log.info("校验缓存是否存在异常",  e);
            return false;
        }
    }

    /**
     * 删除缓存对象
     *
     * @param rkey 缓存池名称
     * @param key  存储key
     */
    public void removeMapCache(String rkey, String key) {
        try {
            RMapCache<Object, Object> mapCache = client.getMapCache(rkey);
            if (mapCache.isExists()) {
                mapCache.remove(key);
            }
        } catch (Exception e) {
            log.info("删除缓存异常", e);
        }
    }


    public long getMapCacheExpireTime(String rkey, String key) {
        long expireTime = -999;
        try {
            RMapCache<Object, Object> mapCache = client.getMapCache(rkey);
            if (mapCache.isExists()) {
                expireTime = mapCache.remainTimeToLive(key);
            }
        } catch (Exception e) {
            log.info("获取缓存元素的过期时间异常", e);
        }
        return expireTime;
    }
}
